package com.adcc.loadsheet.billing.service.impl;

import com.adcc.aoc.devLib.common.log.Log;
import com.adcc.loadsheet.billing.entity.chargerule.BillingLadderEntity;
import com.adcc.loadsheet.billing.entity.chargerule.BillingRuleEntity;
import com.adcc.loadsheet.billing.entity.contractuser.ContractUserEntity;
import com.adcc.loadsheet.billing.entity.export.Billing;
import com.adcc.loadsheet.billing.service.ChargeBillService;
import com.adcc.loadsheet.billing.util.DateTimeUtil;
import com.adcc.loadsheet.billing.util.PrintUtil;
import com.adcc.loadsheet.billing.vo.chargebill.ChargeBillVO;
import com.adcc.loadsheet.billing.vo.chargedetail.ChargeDetailVO;
import com.deepoove.poi.XWPFTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.List;

/**
 * 收费账单Service实现类
 * Created by zhaoml on 2020/4/20.
 */
@Service
public class ChargeBillServiceImpl extends BasisServiceImpl implements ChargeBillService {

    //查询收费账单
    @Override
    public ChargeBillVO getChargeBill(String startDate,String endDate,ContractUserEntity contractUserEntity,List<BillingLadderEntity> billingLadderEntityList){
        return getChargeBillDetail(startDate,endDate,contractUserEntity,billingLadderEntityList);
    }

    @Override
    public String word(String startDate,String endDate,Integer contractUserId,HttpServletResponse response) throws Exception {
        String result = "OK";
        try{
            //填充模板内容，通过合同用户查计费阶梯
            ContractUserEntity contractUserEntity = contractUserEntityMapper.selectByPrimaryKey(contractUserId);
            List<BillingLadderEntity> billingLadderEntityList = billingLadderEntityMapper.selectByBillingRuleId(contractUserEntity.getBillingRuleId());
            mode(startDate,endDate,contractUserEntity,billingLadderEntityList);

            response.setHeader("content-type", "application/octet-stream");
            response.setContentType("application/octet-stream");
            // 下载文件能正常显示中文
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(contractUserEntity.getUserAbbrev() + "收费账单.docx", "UTF-8"));
            // 实现文件下载
            OutputStream out = response.getOutputStream();
            byte[] buffer = new byte[1024];
//            String path = ClassUtils.getDefaultClassLoader().getResource("").getPath();
            FileInputStream fis = new FileInputStream("output.docx");
            BufferedInputStream bis = new BufferedInputStream(fis);
            int i = bis.read(buffer);
            while (i != -1) {
                out.write(buffer, 0, i);
                i = bis.read(buffer);
            }
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    throw e;
                }
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    throw e;
                }
            }
            out.flush();
            out.close();
        }catch (Exception ex1){
            throw ex1;
        }
        return result;
    }

    @Override
    public String pdf(String startDate,String endDate,Integer contractUserId,HttpServletResponse response) throws Exception {
        //填充模板内容，通过合同用户查计费阶梯
        ContractUserEntity contractUserEntity = contractUserEntityMapper.selectByPrimaryKey(contractUserId);
        List<BillingLadderEntity> billingLadderEntityList = billingLadderEntityMapper.selectByBillingRuleId(contractUserEntity.getBillingRuleId());
        mode(startDate,endDate,contractUserEntity,billingLadderEntityList);

        String result = "OK";
//        String path = ClassUtils.getDefaultClassLoader().getResource("").getPath();
        //word装pdf
        try  {
//            InputStream docxInputStream = new FileInputStream("output.docx");
//            OutputStream outputStream = new FileOutputStream("output.pdf");
//            IConverter converter = LocalConverter.builder().build();
//            converter.convert(docxInputStream).as(DocumentType.DOCX).to(outputStream).as(DocumentType.PDF).execute();
//            outputStream.close();
//            File inputFile=new File("output.docx");
//            File outputFile=new File("output.pdf");
//            converter.convert(inputFile).to(outputFile).execute();
            System.out.println("success");
        } catch (Exception e) {
            Log.error(ChargeBillServiceImpl.class,"转换pdf出错",e);
            return e.getMessage();
        }
        //pdf下载
        try{
            response.setHeader("content-type", "application/octet-stream");
            response.setContentType("application/octet-stream");
            // 下载文件能正常显示中文
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(contractUserEntity.getUserAbbrev() + "收费账单.pdf", "UTF-8"));
            // 实现文件下载
            OutputStream out = response.getOutputStream();
            byte[] buffer = new byte[1024];

            FileInputStream fis = new FileInputStream("output.pdf");
            BufferedInputStream bis = new BufferedInputStream(fis);
            int i = bis.read(buffer);
            while (i != -1) {
                out.write(buffer, 0, i);
                i = bis.read(buffer);
            }
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    throw e;
                }
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    throw e;
                }
            }
            out.flush();
            out.close();
        }catch (IOException ex){
            throw ex;
        }catch (Exception ex1){
            throw ex1;
        }
        return result;
    }

    //填充模板内容
    private String mode(String startDate,String endDate,ContractUserEntity contractUserEntity,List<BillingLadderEntity> billingLadderEntityList){
        //查询收费账单
        ChargeBillVO chargeBillVO = getChargeBillDetail(startDate,endDate,contractUserEntity,billingLadderEntityList);
        //数据类填充
        Billing bill = new Billing();
        bill.setTitle(chargeBillVO.getContractUserAbbrev());
        bill.setStarttime(DateTimeUtil.getDateFormatter(startDate));
        bill.setEndtime(DateTimeUtil.getDateFormatter(endDate));
        bill.setLoadsheetnum(chargeBillVO.getLoadsheetnum());
        bill.setPassgerlistnum(chargeBillVO.getPassgerlistnum());
        bill.setRuleRate(chargeBillVO.getRuleRate());
        bill.setRepeatnum(chargeBillVO.getRepeatnum());
        bill.setRepeatrate(chargeBillVO.getRepeatrate());
        bill.setOvernum(chargeBillVO.getOvernum());
        bill.setTotal(chargeBillVO.getTotal());
        bill.setDays(chargeBillVO.getDays());
        bill.setAverage(chargeBillVO.getAverage());
        bill.setCost(chargeBillVO.getCost());

        //将数据类中数据填充到word模板中
        String result = "OK";
        try{
            //相对路径获取
//            String path = ClassUtils.getDefaultClassLoader().getResource("").getPath();
            //billing.docx模板名称
            XWPFTemplate template = XWPFTemplate.compile("billing.docx").render(bill);
            //output.docx数据填充后账单文件
            FileOutputStream out = new FileOutputStream("output.docx");
            template.write(out);
            out.flush();
            out.close();
            template.close();
        }catch (Exception ex){
            result = ex.getMessage();
        }
        return result;
    }

    //获取账单内容
    private ChargeBillVO getChargeBillDetail(String startDate,String endDate,ContractUserEntity contractUserEntity,List<BillingLadderEntity> billingLadderEntityList){
        //计费明细（舱单数据服务航班数、旅客名单服务航班数、当月重发航班数）
        ChargeDetailVO chargeDetailVO = scUpDataEntityMapper.getChargeDetailNum(startDate,endDate,contractUserEntity.getContractUserId());
        //舱单数据服务航班数
        Integer loadsheetnum = chargeDetailVO.getLoadsheetNum();
        //旅客名单服务航班数
        Integer passgerlistnum = chargeDetailVO.getPassgerListNum();
        //当月重发航班数
        Integer repeatnum = chargeDetailVO.getRepeatNum();

        BillingRuleEntity billingRuleEntity = billingRuleEntityMapper.selectByPrimaryKey(contractUserEntity.getBillingRuleId());

        int ruleRate=billingRuleEntity.getRuleRate();

        //重发率（重发率=当月重发航班数/（服务舱单航班数+服务旅客名单航班数），四舍五入取整）
        NumberFormat numberFormat = NumberFormat.getInstance();
        numberFormat.setMaximumFractionDigits(0);
        //乘以100，后面转为百分比
        String repeatrate = (loadsheetnum+passgerlistnum) > 0 ? numberFormat.format((float)repeatnum/(float)(loadsheetnum+passgerlistnum) * 100) : "0";

        //当月超出20%的航班数（超出20%的航班 =当月重发航班数-（月服务舱单航班总数+月服务名单航班总数）*0.2，四舍五入取整）
        Integer overnum = Math.round((float)(repeatnum-(float)(loadsheetnum + passgerlistnum) * ruleRate/100));
        overnum = overnum < 0 ? 0 : overnum;  //负数说明没有超出20%的航班

        //系统月服务航班总数
        Integer total = 0;
        //重发率>20%：系统月服务航班总数=月服务舱单航班总数+月服务旅客名单航班总数+超出20%的航班当月服务航班总数
        //重发率<=20%：系统月服务航班总数=月服务舱单航班总数+月服务旅客名单航班总数
        if(Integer.valueOf(repeatrate) > ruleRate){
            total = loadsheetnum + passgerlistnum + overnum;
        }else {
            total = loadsheetnum + passgerlistnum;
        }
        //重新定义重发率，加上百分号
        repeatrate = repeatrate + "%";

        //本月天数（两个日期包含的天数）
        Integer days = DateTimeUtil.getBetweenDate(startDate,endDate) + 1;
        //本月日均服务航班数（日均服务航班数=系统月服务航班总数/本月天数，四舍五入取整）
        Integer average = (int)Math.round((Double.valueOf(total) / Double.valueOf(days)));
        //本月服务费用（如某月为31天，系统月服务航班总数为5425班，日均服务航班数为175班，则该月系统技术服务费应为61,767.50元）
        String cost = getPrice(average,days,billingLadderEntityList);
        //本月平均单价（元/班）（本月平均单价=本月服务费用/月服务航班数，保留两位小数点）
        DecimalFormat df = new DecimalFormat("0.00");
        String unitPrice = "0.00".equals(cost) ? "0.00" : df.format(Double.valueOf(cost) / total);

        ChargeBillVO chargeBillVO = new ChargeBillVO();
        chargeBillVO.setContractUserAbbrev(contractUserEntity.getUserAbbrev());
        chargeBillVO.setStarttime(startDate);
        chargeBillVO.setEndtime(endDate);
        chargeBillVO.setLoadsheetnum(loadsheetnum.toString());
        chargeBillVO.setPassgerlistnum(passgerlistnum.toString());
        chargeBillVO.setRepeatnum(repeatnum.toString());
        chargeBillVO.setRuleRate(ruleRate);
        chargeBillVO.setRepeatrate(repeatrate.toString());
        chargeBillVO.setOvernum(overnum.toString());
        chargeBillVO.setTotal(total.toString());
        chargeBillVO.setDays(days.toString());
        chargeBillVO.setAverage(average);
        chargeBillVO.setCost("¥ " + cost.toString());
        chargeBillVO.setUnitPrice(unitPrice);
        return chargeBillVO;
    }

    /**
     * 本月服务费用（实现阶梯计费）
     * @param average 本月日均服务航班数
     * @param days 天数
     * @param billingLadderEntityList 计费阶梯
     * @return
     */
    private String getPrice(Integer average,Integer days,List<BillingLadderEntity> billingLadderEntityList){
        //阶梯计费不为空，并且日均服务航班数>0
        if((billingLadderEntityList != null && billingLadderEntityList.size() > 0) && average > 0){
            Double price = 0.00;
            //日均服务单价（阶梯计费）
            BillingLadderEntity lastEntity = null;
            BillingLadderEntity entity = null;
            Integer surplus = average;//每次循环后剩余航班数，初始状态是全部航班数
            for(int i = 0;i < billingLadderEntityList.size();i ++){
                if(lastEntity != null){ //上次循环过，重新定义剩余航班数
                    surplus = average - lastEntity.getLadderEndnumber();
                }
                entity = billingLadderEntityList.get(i);

                if(entity.getLadderStartnumber() <= average && average <= entity.getLadderEndnumber()){
                    price += surplus * entity.getUnitPrice().doubleValue();
                }else if(average > entity.getLadderEndnumber()){
                    price += (entity.getLadderEndnumber() - entity.getLadderStartnumber() + 1) * entity.getUnitPrice().doubleValue();
                }
                lastEntity = entity;
            }
            //保留两位小数点
            DecimalFormat df = new DecimalFormat("0.00");
            return df.format(price * days);
        }else {
            return "0.00";
        }
    }

    //打印
    public void print(String startDate,String endDate,Integer contractUserId,HttpServletResponse response){
        //填充模板内容，通过合同用户查计费阶梯
        ContractUserEntity contractUserEntity = contractUserEntityMapper.selectByPrimaryKey(contractUserId);
        List<BillingLadderEntity> billingLadderEntityList = billingLadderEntityMapper.selectByBillingRuleId(contractUserEntity.getBillingRuleId());
        mode(startDate,endDate,contractUserEntity,billingLadderEntityList);

//        String path = ClassUtils.getDefaultClassLoader().getResource("").getPath()+"/output.docx";
        File file=new File("output.docx");
        PrintUtil.printFile(file.getAbsolutePath(),1);
    }

    //查询收费账单
    @Override
    public ChargeBillVO getChargeBill(Integer loadsheetnum,Integer passgerlistnum,Integer repeatnum,Integer ruleRate,
                                             String startDate,String endDate,
                                             ContractUserEntity contractUserEntity,List<BillingLadderEntity> billingLadderEntityList){
        //重发率（重发率=当月重发航班数/（服务舱单航班数+服务旅客名单航班数），四舍五入取整）
        NumberFormat numberFormat = NumberFormat.getInstance();
        numberFormat.setMaximumFractionDigits(0);
        //乘以100，后面转为百分比
        String repeatrate = (loadsheetnum+passgerlistnum) > 0 ? numberFormat.format((float)repeatnum/(float)(loadsheetnum+passgerlistnum) * 100) : "0";

        //当月超出20%的航班数（超出20%的航班 =当月重发航班数-（月服务舱单航班总数+月服务名单航班总数）*0.2，四舍五入取整）
        Integer overnum = Math.round((float)(repeatnum-(float)(loadsheetnum + passgerlistnum) * ruleRate/100));
        overnum = overnum < 0 ? 0 : overnum;  //负数说明没有超出20%的航班

        //系统月服务航班总数
        Integer total = 0;
        //重发率>20%：系统月服务航班总数=月服务舱单航班总数+月服务旅客名单航班总数+超出20%的航班当月服务航班总数
        //重发率<=20%：系统月服务航班总数=月服务舱单航班总数+月服务旅客名单航班总数
        if(Integer.valueOf(repeatrate) > ruleRate){
            total = loadsheetnum + passgerlistnum + overnum;
        }else {
            total = loadsheetnum + passgerlistnum;
        }
        //重新定义重发率，加上百分号
        repeatrate = repeatrate + "%";

        //本月天数（两个日期包含的天数）
        Integer days = DateTimeUtil.getBetweenDate(startDate,endDate) + 1;
        //本月日均服务航班数（日均服务航班数=系统月服务航班总数/本月天数，四舍五入取整）
        Integer average = (int)Math.round((Double.valueOf(total) / Double.valueOf(days)));
        //本月服务费用（如某月为31天，系统月服务航班总数为5425班，日均服务航班数为175班，则该月系统技术服务费应为61,767.50元）
        String cost = getPrice(average,days,billingLadderEntityList);
        //本月平均单价（元/班）（本月平均单价=本月服务费用/月服务航班数，保留两位小数点）
        DecimalFormat df = new DecimalFormat("0.00");
        String unitPrice = "0.00".equals(cost) ? "0.00" : df.format(Double.valueOf(cost) / total);

        ChargeBillVO chargeBillVO = new ChargeBillVO();
        chargeBillVO.setContractUserAbbrev(contractUserEntity.getUserAbbrev());
        chargeBillVO.setStarttime(startDate);
        chargeBillVO.setEndtime(endDate);
        chargeBillVO.setLoadsheetnum(loadsheetnum.toString());
        chargeBillVO.setPassgerlistnum(passgerlistnum.toString());
        chargeBillVO.setRepeatnum(repeatnum.toString());
        chargeBillVO.setRepeatrate(repeatrate.toString());
        chargeBillVO.setOvernum(overnum.toString());
        chargeBillVO.setTotal(total.toString());
        chargeBillVO.setDays(days.toString());
        chargeBillVO.setAverage(average);
        chargeBillVO.setCost("¥ " + cost.toString());
        chargeBillVO.setUnitPrice(unitPrice);
        return chargeBillVO;
    }
}